home *** CD-ROM | disk | FTP | other *** search
- A TERSE GUIDE TO WCL
-
-
- RUNNING WCL
- -----------
-
- The following development binaries are provied with wcl:
-
- bin/eval - linked with basic CL library.
- bin/wcl - linked with compiler and CL libraries.
- bin/clx - linked with CLXR5, compiler, and CL libraries.
-
- Normally a wcl development binary is run from within emacs. The file
- emacs/wcl.el should loaded into emacs and the value of the emacs
- variables WCL-ROOT-DIRECTORY and WCL-PATH should be set for your site.
- You must also install WGDB and make sure that your path is correctly
- setup to run it.
-
- After these initial steps, The command m-x run-wcl will start wcl
- running under gdb. Once wcl is running, definitions from a lisp file can
- be loaded into the running wcl using the command c-m-x.
-
- When running wcl directly from the command line, the -m switch allows
- you to specify how large you want the heap to be in 1kbyte increments.
- The default size is 8192 (i.e - an 8 meg heap). The -s switch allow you
- to specify the size of static space. Once wcl is started, the heap
- size is fixed (this should be fixed someday). The heap sizes for
- a wcl run using m-x run-wcl must be changed by altering the file
- emacs/gdb-init.gdb.
-
- After wcl has started, it will load an initialzation file named
- ~/.wclinit if it exists.
-
-
- LOADABLE SYSTEMS
- ----------------
-
- Ports of the following systems are provided:
-
- - Cltl2 Pretty Printer - loaded by (load-pprint)
- - PCL: loaded by (load-clos)
- - Logical Pathnames: loaded by (load-logical-pathnames)
-
- Refer to the README file or sources for each system for more details.
-
- CLX
- ---
-
- CLX R5 is provided as a library.
- GCC has a bug which prevents it from compiling CLX correctly, so CC must
- is used instead. Before compiling any files which use CLX functions,
- you must also tell the compiler to use CC:
-
- (progn (lisp::initialize-compiler)
- (setf *target-machine* *sparcstation-cc*))
-
- TO TEST:
- cd to src/clx/test directory
- % clx
- (in-package "XLIB")
- ;;; Compile these files for better performance
- (load "hello.lisp")
- (load "menu.lisp")
-
- (hello-world "")
- (just-say-lisp "")
- (pop-up "" '("chocolate" "strawberry" "asparagus"))
-
-
- EXTENSIONS TO CL
- ----------------
-
- WCL contains some popular extensions to pure CLtl1.
- Refer to the sources and the file lib/rtl/packages/package-setup-info.lisp
- for more information.
-
-
- DEBUGGING WITH WGDB
- -------------------
-
- A slightly modified version of WGDB is used as the debugger for both C
- and Lisp code. It's best to run WGDB from within emacs using m-x gdb.
- Using WGDB with WCL is best explained with a few examples:
-
- file foo.lisp
- --------------
- (in-package "USER")
-
- (defun top (x)
- (middle x))
-
- (defun middle (x)
- (bottom x))
-
- (defun bottom (foo-bar)
- (+ foo-bar 2))
- ------------
-
- First we'll see how WGDB debugs interpreted code by loading foo.lisp and
- calling TOP with a string rather than a number:
-
- > (load "foo.lisp")
- #P"/usr/home/wade/w/current/test/foo.lisp"
-
- > (top "bad arg")
- Error: "bad arg" is not a number
-
- Program received signal 2, Interrupt
- 0xf759c120 in kill
- Debug>
-
- We can get a backtrace with the WGDB command "bt":
- Debug> bt
- #0 0xf759c120 in kill
- #1 0xf76ac6a8 in lisp_debug
- #2 0xf767c4a4 in ERROR
- #3 0xf7675804 in ARITH-ERROR
- #4 0xf76a8c54 in add
- #5 0xf767a898 in +
- #17 0xf76aca7c in BOTTOM (interpreted)
- #29 0xf76aca7c in MIDDLE (interpreted)
- #41 0xf76aca7c in TOP (interpreted)
- #49 0xf76814a0 in REPL-1
- #50 0xf76819dc in REPL
- #51 0x4cf0 in LMAIN
- #52 0x4c5c in RUN-APPLICATION
- #53 0x4c88 in main
-
- Next we can go directly to a specific frame number with the WGDB "frame"
- command. The frame numbers are not always contiguous when debugging
- interpreted code because WGDB is hiding evaluator frames which we normally
- do not want to see. If we do want to see them, the new WGDB "hide" command
- toggles hiding of interpreter frames. For now we'll go directly to
- the frame for BOTTOM:
-
- Debug> frame 17
- #17 0xf76aca7c in BOTTOM (interpreted)
-
- We can now walk up and down the stack with the WGDB "up" and "down"
- commands. Notice that these commands skip hidden frames:
-
- Debug> up
- #29 0xf76aca7c in MIDDLE (interpreted)
- Debug> up
- #41 0xf76aca7c in TOP (interpreted)
- Debug> down
- #29 0xf76aca7c in MIDDLE (interpreted)
- Debug> down
- #17 0xf76aca7c in BOTTOM (interpreted)
-
- Now that we are back in BOTTOM, we can use the new WGDB "eval" command
- to enter an inferior read-eval-print loop in the lexical environment
- of the current frame. This is especially useful for debugging, because
- all variables are available by name:
-
- Debug> eval
-
- Call: (BOTTOM "bad arg")
- Entering debug evaluator. Type :A to exit
- Evaluating forms in the current frame's lexical environment
-
- Eval:1> foo-bar ; look at the value of the argument BOTTOM
- "bad arg"
-
- Eval:1> (inspect foo-bar)
- Inspecting a SIMPLE-STRING at address #x48E35D
-
- [0] #\b
- [1] #\a
- [2] #\d
- [3] #\Space
- [4] #\a
- [5] #\r
- [6] #\g
-
- Command (:H for help): :q
-
- "bad arg"
-
- Eval:1> :a
- $3 = -143023479
-
- :A aborts from the inferior read-eval-print loop back to WGDB. At this
- point we can simply abort the entire computation with the new
- WGDB "abort" command:
-
- Debug> abort
- Aborting to top-level
- Continuing at 0xf76ac684.
-
- Compiled code can also be debugged in a similar manner.
- WGDB will automatically update its symbol table when an object
- file is dynamically loaded into the underlying Lisp process:
-
- > (compile-file "foo")
- #P"foo.o"
-
- > (load *)
- #P"/usr/home/wade/w/current/test/foo.o"
-
- > (top "bad arg")
- Error: "bad arg" is not a number
-
- Program received signal 2, Interrupt
- 0xf759c120 in kill
- Debug> bt
- #0 0xf759c120 in kill
- #1 0xf76ac6a8 in lisp_debug
- #2 0xf767c4a4 in ERROR
- #3 0xf7675804 in ARITH-ERROR
- #4 0xf76a8c54 in add
- #5 0xf6eec17c in BOTTOM at foo.c:51
- #6 0xf6eec11c in MIDDLE at foo.c:41
- #7 0xf6eec080 in TOP at foo.c:31
- #15 0xf76814a0 in REPL-1
- #16 0xf76819dc in REPL
- #17 0x4cf0 in LMAIN
- #18 0x4c5c in RUN-APPLICATION
- #19 0x4c88 in main
- Debug> frame 5
- #5 0xf6eec17c in BOTTOM at foo.c:51
- Source file is more recent than executable.
- Debug> up
- #6 0xf6eec11c in MIDDLE at foo.c:41
- Debug> up
- #7 0xf6eec080 in TOP at foo.c:31
- Debug> down
- #6 0xf6eec11c in MIDDLE at foo.c:41
- Debug> down
- #5 0xf6eec17c in BOTTOM at foo.c:51
-
- We can walk the stack just as we did earlier, but this time GDB shows
- us the name name of the C file and the line number of our compiled
- code. You will also see the corresponding C code displayed in another
- window if you are using WGDB under emacs. Notice that WCL library
- functions such as ERROR have not been compiled with debugging
- information. The WCL library can optionally be compiled with debugging
- information if it is desired. Refer to the installation documentation for
- more details.
-
- WGDB currently cannot debug compiled Lisp code at the Lisp source
- code level. However, it can debug compiled Lisp code at the C source
- level using any existing WGDB commands such as break, step, etc.
- as well as the new WGDB command "lp", which prints the value
- of a variable as a Lisp expression:
-
- Debug> lp v_FOO_2DBAR_0 ; use the mangled Lisp name displayed in source window
- "bad arg"
- $1 = 4706509
- Debug> eval ; or: "eval v_FOO_2DBAR_0" and * is bound to the value of FOO-BAR
-
- Entering debug evaluator. Type :A to exit
- Evaluating forms in the null lexical environment
-
- Eval:1> (+ 1 2)
- 3
-
- Eval:1> :a
- Debug>
-
- Notice that the "eval" command still works with compiled code, but
- unfortunately it does not have access to the current lexical
- environment (although it could be reconstructed), so the null lexical
- environment is used instead. Eval also accepts a variable name as an
- optional argument, and will bind the Lisp symbol "*" to the value of
- that variable upon entering evaluator. As before we can abort back to
- top-level:
-
- Debug> abort
- Aborting to top-level
- Continuing at 0xf76ac684.
-
- >
-
- The new "abort" command is also useful if Lisp is in the middle of a
- long computation or an infinite loop that we could like to end:
-
- > (loop for i from 1 to 1000 do (format t "Iteration ~D~%" i))
- Iteration 1
- Iteration 2
- Iteration 3
- ...
- Iteration 81
- Iteration 82
- ;;; type control-c
-
- Program received signal 2, Interrupt
- 0xf75722d8 in write
- Debug> bt
- #0 0xf75722d8 in write
- #1 0xf7573a58 in _xflsbuf
- #2 0xf757382c in _flsbuf
- #3 0xf75a685c in fputc
- #4 0xf7670630 in WRITE-CHAR/FPTR-STREAM
- #5 0xf7670670 in WRITE-CHAR/TERMINAL-STREAM
- #6 0xf7670360 in WRITE-CHAR/2
- #7 0xf7686e44 in TERPRI
- #8 0xf7651de0 in FORMAT-TERPRI
- #9 0xf764c128 in SUB-FORMAT
- #10 0xf764b580 in FORMAT
- #31 0xf76aca7c in (LAMBDA (I) ...) (interpreted)
- #39 0xf76814a0 in REPL-1
- #40 0xf76819dc in REPL
- #41 0x4cf0 in LMAIN
- #42 0x4c5c in RUN-APPLICATION
- #43 0x4c88 in main
-
- After interrupting the loop, we can continue it with the WGDB
- "continue" command:
-
- Debug> continue
- Continuing.
- Iteration 83
- Iteration 84
- Iteration 85
- ...
- Iteration 289
- Iteration 290
- ;;; type control-c again
-
- Program received signal 2, Interrupt
- 0xf75722d8 in write
- Debug>
-
- We interrupt the loop again and abort to top-level with the
- "abort" command:
-
- Debug> abort
- Aborting to top-level
- Continuing at 0xf76ac684.
-
- >
-
- The new commands "info restarts" and "restart" allow WGDB to interact
- with the CL condition system.
-
- Ultimately, WGDB should be modified to provide full source level
- debugging of Lisp code.
-
-
- LINKING APPLICATIONS AND SHARED LIBRARIES
- ------------------------------------------
-
- Here's a quick example of how to compile and link an application
- consisiting of two files:
-
- file bar.lisp:
- ---------------------
- (in-package "USER")
-
- (defstruct point x y)
- ---------------------
-
- file foo.lisp:
- ---------------------
- (in-package "USER")
-
- (defun lmain ()
- (format t "Point: ~S~%" (make-point :x 3 :y 4)))
- ---------------------
-
- In WCL:
-
- > (compile-file "bar")
- Compiling file #P"bar.lisp"
- Wrote object file #P"bar.o"
- #P"bar.o"
-
- > (compile-file "foo")
- Compiling file #P"foo.lisp"
- Wrote object file #P"foo.o"
- #P"foo.o"
-
- > (link-executable '("foo" "bar"))
- 0 seconds: Reading symbol information
- 1 seconds: Compiling predicates file
- Compiling file #P"/n/kobold/usr1/home/wade/tmp/26123-23preds.lisp"
- Wrote object file #P"/n/kobold/usr1/home/wade/tmp/26123-23preds.o"
- 4 seconds: Writing data file
- 4 seconds: Compiling data file
- 10 seconds: done
- #P"foo"
- >
-
- Now we can run it from a shell:
-
- /home/wade/test> strip foo
- /home/wade/test> size foo
- text data bss dec hex
- 40960 8192 0 49152 c000
- /home/wade/test> foo
- Point: #<POINT 64ADD>
- /home/wade/test>
-
- The file src/build/library-definitions.lisp contains more examples of
- how to link applications and shared libraries.
-
-
- THE COMPILER
- ------------
-
- The compiler is controlled by setting up different configurations.
- refer to com/common/configurations.lisp for more information.
- PROCLAIM is the CL approved way to change configurations.
-
- Array and numeric declarations are used by the compiler to translate
- Lisp array operations and some numeric operations directly into
- equivalent C constructs. Dynamic-extent &rest lists are supported, as
- are &restv lists.
-
-
-
- GARBAGE COLLECTION
- ------------------
-
- The currently collector is based upon the ideas described in Joel
- Bartlett's mostly-copying conservative gc. A single heap area and a
- single static area are used for allocating memory at runtime.
- Statically allocated data can also be located in the data segment of
- a program and any shared libraries that it uses.
-
- The GC should eventually be changed to become generational. Doing
- this could also provide Lisp a general mechanism for setting pointers
- in statically allocated objects. Currently we have to keep track of
- static objects and scan them.
-
- Note that it is possible for a C compiler to generate code which uses
- derived or offset pointers, and thus is not safe for garbage
- collection. This can be big trouble, but Sun cc and gcc don't *seem* to
- have this problem (i.e - they're not that tricky).
-
-
- FOREIGN FUNCTION CALLS
- ----------------------
-
- The macro DEFFOREIGN is used to tell Lisp how to call foreign
- functions:
-
- (defforeign unlink ((path char*) => (status int)))
-
- The foreign function interface is incomplete and needs more work.
- Refer to other examples of how DEFFOREIGN is currently used in the
- system for more information.
-
- Calls from foreign code back into Lisp work equally well, but no
- formal support for them exists. In other words, you need to know the
- mangled name of the Lisp function you want to call, pass an argument
- count, and perform any data conversions yourself.
-
- The macro DEF-C-STRUCT is also useful for describing the layout
- of foreign structures to Lisp.
-
-
- PORTING WCL
- -----------
-
- The dynamic file loader is the most operating system and machine
- dependent part of the system. Currently the dynamic file loader
- only works for SPARCS running SunOS 4.1.
-
- Every machine has a corresponding machine configuration structure
- in the compiler.
-
- These parts of the system are written in assembly language, and
- thus are processor specific:
-
- - Closure allocation and closure garbage collection.
-
- - Fixnum arithmetic handling. Fixnum arithmetic must overflow
- into bignums correctly. On SPARC this is done with an explicit
- overflow check, and on MIPS it is done by the signal handler.
-
- - The garbage collector needs a machine dependent routine to put any
- registers not normally saved by the C calling convention into a
- stack allocated vector.
-
- The actual amount of assembly code is small (perhaps a few dozen lines).
-
- Generic bignum code is available, but machine specific bignum routines
- are also available for a variety of machines. All the sources are in
- the bignum directory.
-
- p.s - There's lots of stuff I haven't put in this document. Send
- mail to wade@sunrise.stanford.edu if you have a question.
-
-